package com.xl.basic.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.param.AddOrUpdRoleMenuParam;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.service.RoleMenuService;
import com.xl.dao.domain.XlRole;
import com.xl.dao.domain.XlRoleMenu;
import com.xl.dao.mapper.XlRoleMapper;
import com.xl.dao.mapper.XlRoleMenuMapper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @author 钟勇
 * Create in 2023/8/30 10:30
 */
@Service
@RequiredArgsConstructor
public class RoleMenuServiceImpl implements RoleMenuService {

    private final XlRoleMenuMapper roleMenuMapper;
    private final XlRoleMapper roleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public Result<Object> addOrUpdRoleMenu(@NonNull AddOrUpdRoleMenuParam param, UserInfo operator) {
        XlRole xlRole = roleMapper.selectById(param.getRoleId());
        if (xlRole == null || xlRole.getState() != 1) {
            return ResultEnums.BusinessError.getResult("未找到对应角色");
        }

        //查询和编辑条件
        LambdaUpdateWrapper<XlRoleMenu> wrapper = new LambdaUpdateWrapper<XlRoleMenu>()
                .eq(XlRoleMenu::getState, 1)
                .eq(XlRoleMenu::getRoleId, param.getRoleId());

        List<XlRoleMenu> oriMenuList = roleMenuMapper.selectList(wrapper);

        String operatorUserId = operator == null ? null : operator.getUserId();


        //如果menuIds传入一个空串，就删除这个角色所有的菜单
        if (StrUtil.isBlank(param.getMenuIds())) {
            if (oriMenuList == null || oriMenuList.isEmpty()) {
                return ResultEnums.Success.getResult();
            }

            if (roleMenuMapper.update(
                    new XlRoleMenu()
                            .setState(0)
                            .setUpdTime(LocalDateTime.now())
                            .setUpdUser(operatorUserId),
                    wrapper
            ) <= 0) {
                return ResultEnums.Exception.getResult("角色菜单保存失败");
            }
        }

        List<Integer> menuIdList;
        try {
            menuIdList = Arrays.stream(param.getMenuIds().split(",")).map(Integer::parseInt).toList();
        } catch (Exception e) {
            return ResultEnums.Exception.getResult("菜单ID数值异常");
        }

        List<Integer> oriMenuIdList = oriMenuList.stream().map(XlRoleMenu::getMenuId).toList();

        //获取新增的菜单id
        List<Integer> addMenuIdList = menuIdList.stream().filter(menuId -> !oriMenuIdList.contains(menuId)).toList();
        //获取移除的菜单id
        List<Integer> delMenuIdList = oriMenuIdList.stream().filter(oriMenuId -> !menuIdList.contains(oriMenuId)).toList();

        if (!addMenuIdList.isEmpty()) {
            for (int menuId : addMenuIdList) {
                if (roleMenuMapper.insert(new XlRoleMenu()
                        .setRoleId(param.getRoleId())
                        .setMenuId(menuId)
                        .setState(1)
                        .setAddTime(LocalDateTime.now())
                        .setAddUser(operatorUserId)
                ) <= 0) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ResultEnums.Exception.getResult("菜单保存失败");
                }
            }
        }

        if (!delMenuIdList.isEmpty()) {
            wrapper.in(XlRoleMenu::getMenuId, delMenuIdList);
            if (roleMenuMapper.update(new XlRoleMenu()
                            .setState(0)
                            .setUpdTime(LocalDateTime.now())
                            .setUpdUser(operatorUserId),
                    wrapper
            ) <= 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ResultEnums.Exception.getResult("菜单移除失败");
            }
        }


        return ResultEnums.Success.getResult();
    }
}
